home *** CD-ROM | disk | FTP | other *** search
/ Aminet 34 / Aminet 34 (2000)(Schatztruhe)[!][Dec 1999].iso / Aminet / util / gnu / unixcmds.lha / unixcmds / src / cut.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-06  |  11.2 KB  |  321 lines

  1. /* cut - extract columns from a file or stdin.  Author: Michael J. Holme
  2.  *
  3.  *      Copyright 1989, Michael John Holme, All rights reserved.
  4.  *      This code may be freely distributed, provided that this notice
  5.  *      remains intact.
  6.  *
  7.  *      V1.1: 6th September 1989
  8.  *
  9.  *      Bugs, criticisms, etc,
  10.  *      c/o Mark Powell
  11.  *          JANET sq79@uk.ac.liv
  12.  *          ARPA  sq79%liv.ac.uk@nsfnet-relay.ac.uk
  13.  *          UUCP  ...!mcvax!ukc!liv.ac.uk!sq79
  14.  *-------------------------------------------------------------------------
  15.  *      Changed for POSIX1003.2/Draft10 conformance
  16.  *      Thomas Brupbacher (tobr@mw.lpc.ethz.ch), September 1990.
  17.  *      Changes:
  18.  *          - separation of error messages ( stderr) and output (stdout).
  19.  *          - support for -b and -n (no effect, -b acts as -c)
  20.  *          - support for -s
  21.  *-------------------------------------------------------------------------
  22.  */
  23.  
  24. #include <sys/types.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30.  
  31. #define MAX_FIELD       80      /* Pointers to the beginning of each field
  32.                          * are stored in columns[], if a line holds
  33.                          * more than MAX_FIELD columns the array
  34.                          * boundary is exceed. But unlikely at 80 */
  35.  
  36. #define MAX_ARGS        32      /* Maximum number of fields following -f or
  37.                          * -c switches                                                                                                    */
  38. int args[MAX_ARGS * 2];
  39. int num_args;
  40.  
  41. /* Lots of new defines, should easen maintainance...                    */
  42. #define DUMP_STDIN      0       /* define for mode: no options   */
  43. #define OPTIONF         1       /* define for mode: option -f    */
  44. #define OPTIONC         2       /* define for mode: option -c    */
  45. #define OPTIONB         3       /* define for mode: option -b    */
  46. #define NOTSET          0       /* option not selected           */
  47. #define SET             1       /* option selected               */
  48.  
  49. /* Defines for the warnings                                             */
  50. #define DELIMITER_NOT_APPLICABLE        0
  51. #define OVERRIDING_PREVIOUS_MODE        1
  52. #define OPTION_NOT_APPLICABLE           2
  53. #define UNKNOWN_OPTION                  3
  54. #define FILE_NOT_READABLE               4
  55.  
  56. /* Defines for the fatal errors                                         */
  57. #define SYNTAX_ERROR                    101
  58. #define POSITION_ERROR                  102
  59. #define USAGE                           103
  60. #define LINE_TO_LONG_ERROR              104
  61. #define RANGE_ERROR                     105
  62. #define MAX_FIELDS_EXEEDED_ERROR        106
  63. #define MAX_ARGS_EXEEDED_ERROR          107
  64.  
  65.  
  66. int mode;                       /* 0 = dump stdin to stdout, 1=-f, 2=-c   */
  67. int flag_i;                     /* SET = -i set on command line  */
  68. int flag_s;                     /* SET = -s set on command line  */
  69. char delim = '\t';              /* default delimiting character   */
  70. FILE *fd;
  71. char *name;
  72. char line[BUFSIZ];
  73. int exit_status;
  74.  
  75. int main  (int argc, char **argv);
  76. void warn  (int warn_number, char *option);
  77. void cuterror  (int err);
  78. void get_args  (void);
  79. void cut  (void);
  80.  
  81. void warn(warn_number, option)
  82. /* [<][>][^][v][top][bottom][index][help] */
  83. int warn_number;
  84. char *option;
  85. {
  86.   static char *warn_msg[] = {
  87.                            "%s: Option -d allowed only with -f\n",
  88.                            "%s: -%s overrides earlier option\n",
  89.                            "%s: -%s not allowed in current mode\n",
  90.                            "%s: Cannot open %s\n"
  91.   };
  92.  
  93.   printf(warn_msg[warn_number], name, option);
  94.   exit_status = warn_number + 1;
  95.  
  96. }
  97.  
  98. void cuterror(err)
  99. /* [<][>][^][v][top][bottom][index][help] */
  100. int err;
  101. {
  102.   static char *err_mes[] = {
  103.                           "%s: syntax error\n",
  104.                           "%s: position must be >0\n",
  105.   "%s: usage: cut [-f args [-i] [-d x]]|[-c args] [filename [...]]\n",
  106.                           "%s: line longer than BUFSIZ\n",
  107.                  "%s: range must not decrease from left to right\n",
  108.                           "%s: MAX_FIELD exceeded\n",
  109.                           "%s: MAX_ARGS exceeded\n"
  110.   };
  111.  
  112.   printf(err_mes[err - 101], name);
  113.   exit(err);
  114. }
  115.  
  116.  
  117. void get_args()
  118. /* [<][>][^][v][top][bottom][index][help] */
  119. {
  120.   int i = 0;
  121.   int arg_ptr = 0;
  122.   int flag;
  123.  
  124.   num_args = 0;
  125.   do {
  126.         if (num_args == MAX_ARGS) cuterror(MAX_ARGS_EXEEDED_ERROR);
  127.  
  128.         printf("line: %s\n",line);
  129.  
  130.         if (!isdigit(line[i]) && line[i] != '-') cuterror(SYNTAX_ERROR);
  131.  
  132.         args[arg_ptr] = 1;
  133.         args[arg_ptr + 1] = BUFSIZ;
  134.         flag = 1;
  135.  
  136.         while ((line[i] != ',') && (line[i] != 0)) {
  137.                 if (isdigit(line[i])) {
  138.                         args[arg_ptr] = 0;
  139.                         while (isdigit(line[i]))
  140.                                 args[arg_ptr] = 10 * args[arg_ptr] + line[i++] - '0';
  141.                         if (!args[arg_ptr]) cuterror(POSITION_ERROR);
  142.                         arg_ptr++;
  143.                 }
  144.                 if (line[i] == '-') {
  145.                         arg_ptr |= 1;
  146.                         i++;
  147.                         flag = 0;
  148.                 }
  149.            /*i++; /* jff add */
  150.         }
  151.         if (flag && (arg_ptr & 1)) args[arg_ptr] = args[arg_ptr - 1];
  152.         if (args[num_args * 2] > args[num_args * 2 + 1])
  153.                 cuterror(RANGE_ERROR);
  154.         num_args++;
  155.         arg_ptr = num_args * 2;
  156.   }
  157.   while (line[i++]);
  158. }
  159.  
  160.  
  161. void cut()
  162. /* [<][>][^][v][top][bottom][index][help] */
  163. {
  164.   int i, j, length, maxcol;
  165.   char *columns[MAX_FIELD];
  166.  
  167.   while (fgets(line, BUFSIZ, fd)) {
  168.         length = strlen(line) - 1;
  169.         *(line + length) = 0;
  170.         switch (mode) {
  171.             case DUMP_STDIN:    printf("%s", line);     break;
  172.             case OPTIONF:
  173.                 maxcol = 0;
  174.                 columns[maxcol++] = line;
  175.                 for (i = 0; i < length; i++) {
  176.                         if (*(line + i) == delim) {
  177.                                 *(line + i) = 0;
  178.                                 if (maxcol == MAX_FIELD)
  179.                                         cuterror(MAX_FIELDS_EXEEDED_ERROR);
  180.                                 columns[maxcol] = line + i + 1;
  181.                                 while (*(line + i + 1) == delim && flag_i) {
  182.                                         columns[maxcol]++;
  183.                                         i++;
  184.                                 }
  185.                                 maxcol++;
  186.                         }
  187.                 }
  188.                 if (maxcol == 1) {
  189.                         if (flag_s != SET) printf("%s", line);
  190.                 } else {
  191.                         for (i = 0; i < num_args; i++) {
  192.                                 for (j = args[i * 2]; j <= args[i * 2 + 1]; j++)
  193.                                         if (j <= maxcol) {
  194.                                                 printf("%s", columns[j - 1]);
  195.                                                 if (i != num_args - 1 || j != args[i * 2 + 1])
  196.                                                         putchar(delim);
  197.                                         }
  198.                         }
  199.                 }
  200.                 break;
  201.             case OPTIONC:
  202.                 for (i = 0; i < num_args; i++) {
  203.                         for (j = args[i * 2]; j <= (args[i * 2 + 1] > length ? length :
  204.                                               args[i * 2 + 1]); j++)
  205.                                 putchar(*(line + j - 1));
  206.                 }
  207.         }
  208.         if (maxcol == 1 && flag_s == SET);
  209.         else
  210.                 putchar('\n');
  211.   }
  212. }
  213.  
  214.  
  215. int main(argc, argv)
  216. /* [<][>][^][v][top][bottom][index][help] */
  217. int argc;
  218. char *argv[];
  219. {
  220.   int i = 1;
  221.   int numberFilenames = 0;
  222.   name = argv[0];
  223.  
  224.   if (argc == 1) cuterror(USAGE);
  225.  
  226.   while (i < argc) {
  227.         if (argv[i][0] == '-') {
  228.                 switch (argv[i++][1]) {
  229.                     case 'd':
  230.                         if (mode == OPTIONC || mode == OPTIONB)
  231.                                 warn(DELIMITER_NOT_APPLICABLE, "d");
  232.                         delim = argv[i++][0];
  233.                         break;
  234.                     case 'f':
  235.                         sprintf(line, "%s", argv[i++]);
  236.                         if (mode == OPTIONC || mode == OPTIONB)
  237.                                 warn(OVERRIDING_PREVIOUS_MODE, "f");
  238.                         mode = OPTIONF;
  239.                         break;
  240.                     case 'b':
  241.                         sprintf(line, "%s", argv[i++]);
  242.                         if (mode == OPTIONF || mode == OPTIONC)
  243.                                 warn(OVERRIDING_PREVIOUS_MODE, "b");
  244.                         mode = OPTIONB;
  245.                         break;
  246.                     case 'c':
  247.                         sprintf(line, "%s", argv[i++]);
  248.                         if (mode == OPTIONF || mode == OPTIONB)
  249.                                 warn(OVERRIDING_PREVIOUS_MODE, "c");
  250.                         mode = OPTIONC;
  251.                         break;
  252.                     case 'i':   flag_i = SET;   break;
  253.                     case 's':   flag_s = SET;   break;
  254.                     case '\0':  /* - means: read from stdin              */
  255.                         numberFilenames++;
  256.                         break;
  257.                     case 'n':   /* needed for Posix, but no effect here  */
  258.                         if (mode != OPTIONB)
  259.                                 warn(OPTION_NOT_APPLICABLE, "n");
  260.                         break;
  261.                     default:
  262.                         warn(UNKNOWN_OPTION, &(argv[i - 1][1]));
  263.                 }
  264.         } else {
  265.                 i++;
  266.                 numberFilenames++;
  267.         }
  268.   }
  269.  
  270. /* Here follow the checks, if the selected options are reasonable.      */
  271.   if (mode == OPTIONB)          /* since in Minix char := byte           */
  272.         mode = OPTIONC;
  273. /* Flag -s is only allowed with -f, otherwise warn and reset flag_s     */
  274.   if (flag_s == SET && (mode == OPTIONB || mode == OPTIONC)) {
  275.         warn(OPTION_NOT_APPLICABLE, "s");
  276.         flag_s = NOTSET;
  277.   }
  278.  
  279. /* Flag -i is only allowed with -f, otherwise warn and reset flag_i     */
  280.   if (flag_i == SET && mode == OPTIONF) {
  281.         warn(OPTION_NOT_APPLICABLE, "s");
  282.         flag_i = NOTSET;
  283.   }
  284.   get_args();
  285.   if (numberFilenames != 0) {
  286.         i = 1;
  287.         while (i < argc) {
  288.                 if (argv[i][0] == '-') {
  289.                         switch (argv[i][1]) {
  290.                             case 'f':
  291.                             case 'c':
  292.                             case 'b':
  293.                             case 'd':   i += 2; break;
  294.                             case 'n':
  295.                             case 'i':
  296.                             case 's':   i++;    break;
  297.                             case '\0':
  298.                                 fd = stdin;
  299.                                 i++;
  300.                                 cut();
  301.                                 break;
  302.                             default:    i++;
  303.                         }
  304.                 } else {
  305.                         if ((fd = fopen(argv[i++], "r")) == NULL) {
  306.                                 warn(FILE_NOT_READABLE, argv[i - 1]);
  307.                         } else {
  308.                                 cut();
  309.                                 fclose(fd);
  310.                         }
  311.                 }
  312.         }
  313.   } else {
  314.         fd = stdin;
  315.         cut();
  316.   }
  317.  
  318.   return(exit_status);
  319. }
  320. /* [<][>][^][v][top][bottom][index][help] */
  321.